package com.smarttest.portal.controller;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.g7s.test.utils.common.CommonUtils;
import com.smarttest.common.beans.GeneralResultWithStatus;
import com.smarttest.common.beans.JsonDataResult;
import com.smarttest.common.beans.TestResult;
import com.smarttest.portal.pojo.DbAutoSetting;
import com.smarttest.portal.service.Autog7Service;
import com.smarttest.portal.service.FileService;
import com.smarttest.portal.service.GetAutoFunctionService;
import com.smarttest.portal.service.timertask.AutoTimerTask;
@RequestMapping("/autog7")
@Controller
public class InterfaceAutoController {
	@Autowired
	GetAutoFunctionService getAutoFunc;
	@Autowired
	Autog7Service autog7;
	@Autowired
	FileService fileService;
	@Autowired
	AutoTimerTask AutoTimerTask;
	
	/**
	 * 获取所有断言函数及其参数
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/getAssertFunction.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus getAssertFunction(HttpServletRequest request) {
		List<Method> assertfunc = getAutoFunc.getAssertFunction();
    	ParameterNameDiscoverer pnd=new DefaultParameterNameDiscoverer();
		String ss = "<option value=\"\" selected=\"selected\">-请选择-</option>";
		for (Method m : assertfunc) {
			List<String> parameterNamesList = new ArrayList<String>();			
			if (pnd.getParameterNames(m) != null) {
				parameterNamesList = Arrays.asList(pnd.getParameterNames(m));
			}
			String [] parameterNames = parameterNamesList.toArray(new String[parameterNamesList.size()]);
			Class<?> [] ptype= m.getParameterTypes();
			String paramstr = "";
			if (ptype.length != parameterNames.length) {
				System.out.println(m.getName());
				throw new RuntimeException("反射获得参数类型数与参数条数不一致");
			}
			for (int i = 0; i < parameterNames.length; i++) {
				if (!paramstr.isEmpty()) {
					paramstr+=",";
				}
				paramstr += ptype[i].getSimpleName() + "	" + parameterNames[i];
			}
			ss += "<option classname=\""+m.getDeclaringClass().getName()+"\" value=\""+m.getName()+"("+paramstr+")\">"+m.getName()+"("+paramstr+")"+"</option>";
		}
		return GeneralResultWithStatus.okData(null, ss);
	}
	/**
	 * 获得所有取值函数及其入参
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/getParamsFunction.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus getParamsFunction(HttpServletRequest request) {
		List<Method> assertfunc = getAutoFunc.getParamsFunction();
    	ParameterNameDiscoverer pnd=new DefaultParameterNameDiscoverer();
		String ss = "<option value=\"\" selected=\"selected\">-请选择-</option>";
		for (Method m : assertfunc) {
			List<String> parameterNamesList = new ArrayList<String>();			
			if (pnd.getParameterNames(m) != null) {
				parameterNamesList = Arrays.asList(pnd.getParameterNames(m));
			}
			String [] parameterNames = parameterNamesList.toArray(new String[parameterNamesList.size()]);
			Class<?> [] ptype= m.getParameterTypes();
			String paramstr = "";
			if (ptype.length != parameterNames.length) {
				System.out.println(m.getName());
				throw new RuntimeException("反射获得参数类型数与参数条数不一致");
			}
			for (int i = 0; i < parameterNames.length; i++) {
				if (!paramstr.isEmpty()) {
					paramstr+=",";
				}
				paramstr += ptype[i].getSimpleName() + "	" + parameterNames[i];
			}
			ss += "<option classname=\""+m.getClass().getName()+"\" value=\""+m.getName()+"("+paramstr+")\">"+m.getName()+"("+paramstr+")"+"</option>";
		}
		return GeneralResultWithStatus.okData(null, ss);
	}
	@RequestMapping(value = "/initData.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus initData(String datainits) {
		try {
			autog7.initData(datainits);
		}
		catch (Exception e) {
			return GeneralResultWithStatus.error(e.getMessage());

		}
		return GeneralResultWithStatus.ok(null);
	}
	@RequestMapping(value = "/debugTest.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus debugTest(HttpServletRequest request) {
		String apiurl = request.getParameter("apiurl");
		String httpmethod = request.getParameter("httpmethod");
		Boolean dataAsParams = Boolean.valueOf(request.getParameter("dataAsParams"));
		String outerparams = request.getParameter("outerparams");
		JSONObject jo = JSON.parseObject(outerparams);
		String cases = request.getParameter("cases");
//		JSONArray ja = JSON.parseArray(cases);
		JSONObject jsoncases = JSON.parseObject(cases);
//		List<TestResult> l = new ArrayList<TestResult>();
//		for (Object o : ja) {
//			TestResult tr = autog7.debugTest(apiurl, httpmethod, jo, dataAsParams, (JSONObject)o);
//			l.add(tr);
//		}
		TestResult tr = autog7.debugTest(apiurl, httpmethod, jo, dataAsParams,jsoncases);
		return GeneralResultWithStatus.okData(null, tr);
	}
	@RequestMapping(value = "/runTest.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus runTest(int detailid,int sumresultid) {
		TestResult tr = null;
		tr = autog7.runTest(detailid,sumresultid);
		return GeneralResultWithStatus.okData(null, tr);
	}
	
	@RequestMapping(value = "/getDetailIds.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus getDetailIds(int sumid) {
		String str = autog7.getDetailsIds(sumid);
		return GeneralResultWithStatus.okData(null, str);
	}
	
	@RequestMapping(value = "/batchDeleteSummary.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public JsonDataResult deleteTest(String idsStr) {
		if (idsStr == null)
			return JsonDataResult.error(300);
		String[] idsarr = idsStr.split(",");
		if (idsarr.length <= 0) {
			return JsonDataResult.error(300);
		}
		List<Integer> ids = new ArrayList<Integer>();
		for (String each : idsarr) {
			ids.add(Integer.parseInt(each));
		}
		try{
		int result = autog7.deleteCases(ids);
		return JsonDataResult.ok(result);
		}catch(Exception e){
			e.printStackTrace();
			return JsonDataResult.error(100);
		}
	}
	
	@RequestMapping(value = "/getTimerTaskList.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public HashMap<String, Object> getTimerTaskList(String key,String sortField, String sortOrder,int pageIndex, int pageSize) {
		return autog7.getTimerTaskList(key, pageIndex, pageSize, sortField, sortOrder);
	}
	@RequestMapping(value = "/updateTimerTaskList.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public int updateTimerTaskList(String data) {		
		return autog7.updateTimerTaskList(JSON.parseArray(data));
	}
	@RequestMapping(value = "/addTimerTask.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus addTimerTask(int envid, int releaseid,String describing, String testids, String jobdetails, int exctype, String runtime) {
		AutoTimerTask.addTimerTask(envid, releaseid,describing, testids, jobdetails, exctype, runtime);
		return GeneralResultWithStatus.ok(null);
	}
	@RequestMapping(value = "/getModuleidBySumid", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus getModuleidBySumid(int sumid) {
		return GeneralResultWithStatus.okData(null,autog7.getModuleBySumid(sumid));
	}
	/**
	 * 初始自动化配置
	 * @param env
	 * @param modules
	 * @return
	 */
	@RequestMapping(value = "/handleSetting.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus handleSetting(int env, String modules) {
		try {
			List<DbAutoSetting> ls = autog7.getSettingBefore(env, modules);
			ThreadPoolExecutor pool = new ThreadPoolExecutor(
	
				    20,100,600,
	
				    TimeUnit.SECONDS, 
	
				    new ArrayBlockingQueue<Runnable>(10),
	
				    new ThreadPoolExecutor.CallerRunsPolicy());
			//不同模块的数据初始化采用多线程并发
			for (final DbAutoSetting setting : ls) {
				Runnable r = new Runnable() {
					@Override
					public void run() {
						for (Object o : JSON.parseArray(setting.getSetting())) {
							if (((JSONObject)o).getString("type").equalsIgnoreCase("message")) {
								JSONArray ja = ((JSONObject)o).getJSONArray("data");
								 Vector<Thread> threads = new Vector<Thread>();
								 for (final Object oo : ja) {
									 Thread t = new Thread(new Runnable() {
											@Override
											public void run() {
												JSONObject jo = ((JSONObject)oo);
												String msg_sendmethod = jo.getString("msg_sendmethod");
												String msg_add = jo.getString("msg_add");
												Integer msg_port = jo.getInteger("msg_port");
												String msg_sendtime = jo.getString("msg_sendtime");
												String msg_format = jo.getString("msg_format");
												Integer msg_internal = jo.getInteger("msg_internal");
												String msg_text = jo.getString("msg_text");
												String msg_startnum = jo.getString("msg_startnum");
												String msg_count = jo.getString("msg_count");
												String msg_key = jo.getString("msg_key");
												autog7.sendMsg(msg_sendmethod, msg_add, msg_port, msg_sendtime, msg_format, msg_internal,msg_text, msg_startnum, msg_count, msg_key);
											}
									 });
									 threads.add(t);
									t.start();
								 }
								 for (Thread iThread : threads) {  
								      try {  
								        // 等待所有线程执行完毕  
								        iThread.join();  
								      } catch (InterruptedException e) {  
								        e.printStackTrace();  
								      }  
								} 
							}				
						}
					}
				};
				Future<?> f = pool.submit(r);
				while (true) {
					if (f.isDone()) {
						break;
					}			
				}
			}
			return GeneralResultWithStatus.ok(null);
		}
		catch (Exception e) {
			return GeneralResultWithStatus.error("初始自动化失败");
		}
	}
	/**
	 * 对外接口，使用方式同dsp接口调用，如传参 "dsp_test","modules","xxx","internames","xxx"......
	 * @param env 必传参数
	 * @param params
	 * @return
	 */
	@RequestMapping(value = "/runTests.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus runTests(String env, Object ... params) {
		if (CommonUtils.isStrEmpty(env)) {
			return GeneralResultWithStatus.error(null,"测试环境不能为空");
		}
		String modules = null;
		String internames = null;
		String testers = null;
		String degrees = null;
		String release = null;
		int level = -1;	
		JSONObject jo = new JSONObject();
		for (int i = 0; i < params.length; i += 2) {
			jo.put(params[i].toString(), params[i+1]);
		}
		modules = jo.getString("modules");
		internames = jo.getString("internames");
		testers = jo.getString("testers");
		degrees = jo.getString("degrees");
		release = jo.getString("release");
		level = jo.getIntValue("level");
		JSONObject testids = autog7.getTestIds(env, modules, internames, testers, degrees, level);	
		int releaseid = autog7.createNewRelease(autog7.getEnvid(env), release, testids.toJSONString());
		return autog7.runTest(testids,releaseid);
	}
	
	@RequestMapping(value = "/updateSumResult.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus updateSumResult(Integer sumid,Integer sumresultid, int lastresult) {
		String result = "";
		if (lastresult == 0) {
			result = "PASS";
		}
		else if (lastresult == 1) {
			result = "FAIL";
		}
		else if (lastresult == 2) {
			result = "SKIP";
		}
		int resultnum = autog7.updateSumResult(sumid, sumresultid,lastresult, new Date(),result);
		return GeneralResultWithStatus.okData(null, resultnum);
	}
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/importCase.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus importCase(HttpServletRequest request,@RequestParam("files") MultipartFile[] files) {
		String userName = request.getRemoteUser();
		Object result = fileService.uploadExcelCaseWithUser(userName, files);
		if(result instanceof Integer && (int)result ==500){
			return GeneralResultWithStatus.error("上传异常");
		}else{			
			int num = autog7.importCaseFromExcel((List<String>)result);
			return GeneralResultWithStatus.okData(null, num);
		}
	}
	@RequestMapping(value = "/createRelease.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus createRelease(Integer envid,String name, String testids) {
		return GeneralResultWithStatus.okData(null, autog7.createNewRelease(envid, name, testids));
	}
	@RequestMapping(value = "/insertSumResult.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus insertSumResult(Integer sumid,Integer releaseid) {
		return GeneralResultWithStatus.okData(null, autog7.insertSumResult(sumid, releaseid));
	}
	@RequestMapping(value = "/getReleaseName.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus getReleaseName(Integer releaseid) {
		return GeneralResultWithStatus.okData(null, autog7.getReleaseName(releaseid));
	}
	@RequestMapping(value = "/getDatainitsBySumid.action", method = {RequestMethod.GET,RequestMethod.POST})
	@ResponseBody
	public GeneralResultWithStatus getDatainitsBySumid(Integer sumid) {
		return GeneralResultWithStatus.okData(null, autog7.getDatainitsBySumid(sumid));
	}
}
